;there is subtle difference between these contradictive predicate
;cannot simply negate them
(define not_symbol
	(lambda (x)
		(if (symbol? x)
			#f
			(if (is_not x)
				#f
				#t
			)
		)
	)
)


(define is_negate
	(lambda (x y)
		;(begin (pp (list "is_negate x=" x "y=" y))
		(cond
			((and(symbol? x)(symbol? y)) #f)
			((and(list? x)(list? y)) #f)
			((and(is_not x)(symbol? y))(eq? (cadr x) y))
			((and(symbol? x)(is_not y))(eq? x (cadr y)))
			(else #f)
		)
		;)
	)
)


(define clauselength
	(lambda (ls)
		(if (is_symbol ls)
			0
			(- (length ls) 1)
		)
	)
)

(define is_symbol
	(lambda (x)
		(or (symbol? x)(is_not x))
	)
)

(define is_not
	(lambda (ls)
		(if (or(symbol? ls)(boolean? ls))
			#f
			(eq? (car ls) 'NOT)
		)
	)
)

(define is_or
	(lambda (ls)
		(if (symbol? ls)
			#f
			 (eq? (car ls) 'OR)	
		)		
	)
)

(define is_and
	(lambda (ls)
		(if (symbol? ls)
			#f
			(eq? (car ls) 'AND)
		)
	)
)

;this is my own limited version of "map"
(define foreach
	(lambda (f)
		(lambda (ls)
			(if   (null? ls)
				'()
				(cons (f (car ls)) ((foreach f) (cdr ls)))
			)
		)
	)
)

;"this is my own limited version of "append"
(define concat 
	(lambda (ls1 ls2)
		(if (null? ls1)
			ls2
			(cons (car ls1) (concat (cdr ls1) ls2))
		)
	)
)

(define concatlist
	(lambda (ls)
		(if (null? ls)
			'()
			(concat (car ls) (concatlist (cdr ls)))
		)
	)
)


(define term2string
	(lambda (ls)
		(if (is_not ls)
			(symbol->string (cadr ls))
			(symbol->string ls)
		)
	)
)

(define termcomp
	(lambda (ls1 ls2)
		(if (string=? (term2string ls1)(term2string ls2))
			(if (and (is_not ls1)(symbol? ls2));  define "not A" < "A"
				#t
				#f ;all other cases assume they are not ls1<ls2
			)
			(string<? (term2string ls1)(term2string ls2))
		)
	)
)


(define generic_insert
	(lambda (f)
		(lambda (x ls)
			(if (null? ls)
				(list x)
				(if (f x (car ls))
					(cons x ls)
					(cons (car ls) ((generic_insert f) x (cdr ls)))
				)
			)
		)
	)
)		


; a general purpose sorting algorithm which is a bubble sort with user defined compare method
; as parameter f. 
(define generic_sort
	(lambda (f)
		(lambda (ls)
			(if (null? (cdr ls))
				ls
				((generic_insert f) (car ls) ((generic_sort f) (cdr ls)))
			)
		)
	)
)

(define generic_insert_unique
	(lambda (fsmall fequal)
		(lambda (x ls)
			;(begin (pp (list "insert x=" x "ls=" ls))
			(if (null? ls)
				(list x)
				(if (fsmall x (car ls))					
					(cons x ls)
					(if (fequal x (car ls))
						ls ;find repeat
						(cons (car ls) ((generic_insert_unique fsmall fequal) x (cdr ls)))
					)
				)
			)
			;)
		)
	)
)		

(define is_keyword
	(lambda (x)
		(or (eq? x 'AND)(eq? x 'OR))
	)
)

; a general purpose sorting algorithm which is a bubble sort with user defined compare method
; as parameter f. 
(define generic_sort_unique
	(lambda (fsmall fequal)
		(lambda (ls)
			;(begin (pp (list "sort ls=" ls))
			(if (null? ls)
				'()
				(if (not_symbol (car ls))
					((generic_insert_unique fsmall fequal) ((generic_sort_unique fsmall fequal)(car ls))
						((generic_sort_unique fsmall fequal)(cdr ls)))
					(if (is_keyword (car ls))
						(cons (car ls)((generic_sort_unique fsmall fequal)(cdr ls)))					
						((generic_insert_unique fsmall fequal) (car ls) 
							((generic_sort_unique fsmall fequal) (cdr ls)))
					)
				)
			)
			;)
		)
	)
)


